package com.zuilapsa.jmc.userInterfaces.telnet;

import java.net.*;
import java.util.*;
import java.io.*;
import org.dom4j.*;

import com.zuilapsa.jmc.*;
import com.zuilapsa.jmc.model.*;
import com.zuilapsa.jmc.userInterfaces.UserInterfaceSession;


public class TelnetInterfaceSession extends Thread implements UserInterfaceSession {
	TelnetInterfaceSession deamon;

	Socket socket;

	PrintWriter out;

	BufferedReader in;

//	Element config = null;
//
//	Element definition = null;
	
	Level level = null;

	public TelnetInterfaceSession(Socket socket) {
		super("TelnetSession");
		this.socket = socket;
		try {
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
		} catch (IOException e) {
			startStopping();
		}
		deamon = this;
		try {
			level = Level.getRootInstance();
		} catch (JmcException e) {
		}
	}

	public void run() {
		Thread thisThread = Thread.currentThread();
		String inputLine, outputLine;

		outputLine = processInput(null);
		if (outputLine != null)
			out.print(outputLine);
		out.print(getPrompt());
		out.flush();

		try {
			while ((deamon == thisThread)
					&& ((inputLine = in.readLine()) != null)) {
				
				outputLine = processInput(inputLine);
				if (outputLine != null)
					out.print(outputLine);
				if (deamon != null) {
					out.print(getPrompt());
					out.flush();
				}
			}
			System.out.println(getName() + ": closing connection");
		} catch (IOException e) {
			System.err.println(getName() + ": connection lost");
			startStopping();
		}
		try {
			out.close();
			in.close();
			socket.close();
		} catch (IOException e) {
			System.err.println(getName() + ": error closing the connection");
		}
	}

	public void startStopping() {
		deamon = null;
	}

	public void printMessageInfo(String message) {
		out.println(message);
	}
	
	public void printMessageWarning(String message) {
		out.println("[?] "+message);
	}

	public void printMessageError(String message) {
		out.println("[!] " + message);
	}

	public Element getConfigElement() {
		return getLevel().getConfigElement();
	}
	
	public Element getDefinitionElement() {
		return getLevel().getDefinitionElement();
	}

//	protected Element setConfigElement(Element element) {
//		config = element;
//		return element;
//	}
//
//	protected Element setDefinitionElement(Element element) {
//		definition = element;
//		return element;
//	}

	public String getPrompt() {
		String theOutput = null;
//		try {
			List pathElements = getLevel().getPath();
//			Configuration.getInstance().getPath(
//					getConfigElement());
			pathElements.remove(0); // remove root element from path as there
									// will be always only one root
			theOutput = Configuration.listPathToString(pathElements);
//		} catch (JmcException e) {
//			printMessageError("Fatal error: lost in the bush");
//			theOutput = null;
//		}
		return theOutput + " > ";
	}

	public String processInput(String theInput) {
		if (theInput == null) {
			printMessageInfo("Welcome to managament console");
			return null;
		} else if (theInput.length() == 0) {
			return null;
		} else {
			Hashtable avalibleTokens;
			try {
				avalibleTokens = getLevel().getTokens();
			} catch (JmcException e) {
				printMessageError("Fatal error creating tokens table");
				return null;
			}
			String[] command = theInput.split(" ", 2);

			String[] inputTokens = null;
			if (command.length != 1) {
				inputTokens = command[1].split(" ");
			}

			try {
				executeToken(avalibleTokens, command[0], inputTokens);
			} catch (JmcException e) {
				printMessageError(e.getMessage());
				return null;
				// ERROR";
			} catch (Exception e) {
				printMessageError(e.getMessage());
				return null;
			}
			return null;

		}
	}


	public void executeToken(Hashtable tokens, String tokenName, String[] arguments)
			throws JmcException {
		Token token = (Token)tokens.get(tokenName);
		if (token != null) 
			token.execute(this, arguments);
		else
			printMessageError("No such command");
	}

	// public void enterLevel(String levelString) {
	// // TODO Auto-generated method stub
	//		
	// }


	public Level getLevel() {
		return level;
	}

	public void setLevel(Level level) {
		this.level = level;
	}

	public Level getModel() {
		try {
			return Level.getRootInstance();
		} catch (JmcException e) {
			printMessageError(e.getMessage());
			return null;
		}
	}
	
}
